package org.jeecg.util;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RepeaterServer {
    private static final int UDP_PORT = 5000;
    private static final Map<InetSocketAddress, DeviceSession> sessions = new ConcurrentHashMap<>();

    public static void main(String[] args) throws IOException {
        try (DatagramSocket socket = new DatagramSocket(UDP_PORT)) {
            byte[] buffer = new byte[1500]; // AP:C最大长度1500

            while (true) {
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet);

                // 解码协议消息
                ProtocolMessage message = ProtocolCodec.decode(
                        Arrays.copyOf(packet.getData(), packet.getLength()));

                // 处理消息
                InetSocketAddress deviceAddress = new InetSocketAddress(
                        packet.getAddress(), packet.getPort());

                ProtocolMessage response = processMessage(message, deviceAddress);

                if (response != null) {
                    byte[] responseData = ProtocolCodec.encode(response);
                    DatagramPacket responsePacket = new DatagramPacket(
                            responseData, responseData.length, deviceAddress);
                    socket.send(responsePacket);
                }
            }
        }
    }

    private static ProtocolMessage processMessage(ProtocolMessage message,
                                                  InetSocketAddress deviceAddress) {
        ProtocolMessage response = new ProtocolMessage();

        // 复制地址和包ID
        response.address = message.address;
        response.packetId = message.packetId;
        response.vpFlag = 0x00; // 正常执行
        response.cpid = message.cpid;

        // 处理不同类型命令
        switch (message.commandId) {
            case ProtocolConstants.CMD_ALARM_REPORT:
                return handleAlarmReport(message, response);

            case ProtocolConstants.CMD_QUERY:
                return handleQuery(message, response);

            case ProtocolConstants.CMD_SET:
                return handleSet(message, response);

            default:
                response.ackFlag = 0x02; // 命令编号错
                return response;
        }
    }

    private static ProtocolMessage handleAlarmReport(ProtocolMessage message,
                                                     ProtocolMessage response) {
        response.commandId = ProtocolConstants.CMD_ALARM_REPORT;
        response.ackFlag = 0x00; // 成功

        // 查找上报类型
        for (MonitorData data : message.monitorDataList) {
            if (data.id == ProtocolConstants.REPORT_TYPE) {
                // 处理不同类型上报
                byte reportType = data.value[0];
                if (reportType == 2) { // 开站上报
                    handleStationSetup(response);
                } else if (reportType == 1) { // 告警上报
                    handleAlarmData(message, response);
                }
                break;
            }
        }
        return response;
    }

    private static void handleStationSetup(ProtocolMessage response) {
        // 添加开站上报响应
        MonitorData reportData = new MonitorData();
        reportData.id = ProtocolConstants.REPORT_TYPE;
        reportData.length = 3; // 长度1 + ID2
        reportData.value = new byte[]{2}; // 开站上报类型
        response.monitorDataList.add(reportData);
    }

    private static ProtocolMessage handleQuery(ProtocolMessage message,
                                               ProtocolMessage response) {
        response.commandId = ProtocolConstants.CMD_QUERY;
        response.ackFlag = 0x00;

        for (MonitorData query : message.monitorDataList) {
            MonitorData data = new MonitorData();
            data.id = query.id;

            if (query.id == ProtocolConstants.DEVICE_INFO_LIST) {
                populateDeviceInfo(data);
            }
            else if (isInRange(query.id, ProtocolConstants.ALARM_ENABLE_START,
                    ProtocolConstants.ALARM_ENABLE_END)) {
                populateAlarmEnable(query.id, data);
            }
            else if (isInRange(query.id, ProtocolConstants.ALARM_STATUS_START,
                    ProtocolConstants.ALARM_STATUS_END)) {
                populateAlarmStatus(query.id, data);
            }
            else if (isInRange(query.id, ProtocolConstants.REAL_TIME_DATA_START,
                    ProtocolConstants.REAL_TIME_DATA_END)) {
                populateRealTimeData(query.id, data);
            }

            response.monitorDataList.add(data);
        }
        return response;
    }

    private static ProtocolMessage handleSet(ProtocolMessage message,
                                             ProtocolMessage response) {
        response.commandId = ProtocolConstants.CMD_SET;
        response.ackFlag = 0x00;

        for (MonitorData setData : message.monitorDataList) {
            if (isInRange(setData.id, ProtocolConstants.ALARM_ENABLE_START,
                    ProtocolConstants.ALARM_ENABLE_END)) {

                // 更新告警使能状态
                updateAlarmEnable(setData.id, setData.value);

                // 返回设置值作为响应
                MonitorData respData = new MonitorData();
                respData.id = setData.id;
                respData.length = (byte)(3 + setData.value.length);
                respData.value = setData.value;
                response.monitorDataList.add(respData);
            } else {
                response.ackFlag = 0x01; // 有条件执行错误
                // 添加错误指示
                MonitorData errorData = new MonitorData();
                errorData.id = (short)(setData.id | 0x1000); // 错误标识
                errorData.length = 3;
                response.monitorDataList.add(errorData);
            }
        }
        return response;
    }

    // 辅助方法
    private static boolean isInRange(int id, int start, int end) {
        return id >= start && id <= end;
    }

    // 以下为模拟数据填充方法
    private static void populateDeviceInfo(MonitorData data) {
        // 模拟设备信息
        data.length = 20; // 实际长度计算
        // 填充设备信息...
    }

    private static void populateAlarmEnable(short alarmId, MonitorData data) {
        // 模拟告警使能状态
        data.length = 4; // 1字节长度+2字节ID+1字节值
        data.value = new byte[]{1}; // 使能状态
    }

    private static void populateAlarmStatus(short alarmId, MonitorData data) {
        // 模拟告警状态
        data.length = 4;
        data.value = new byte[]{0}; // 正常状态
    }

    private static void populateRealTimeData(short dataId, MonitorData data) {
        // 模拟实时采样数据
        data.length = 6; // 1+2+2
        data.value = ByteBuffer.allocate(2)
                .order(ByteOrder.LITTLE_ENDIAN)
                .putShort((short)1234) // 采样值
                .array();
    }

    private static void updateAlarmEnable(short alarmId, byte[] value) {
        // 实际实现中更新设备状态
        System.out.printf("Updated alarm enable 0x%04X to %d%n", alarmId, value[0]);
    }

    private static void handleAlarmData(ProtocolMessage message, ProtocolMessage response) {
        // 处理告警数据
        for (MonitorData alarm : message.monitorDataList) {
            if (isInRange(alarm.id, ProtocolConstants.ALARM_STATUS_START,
                    ProtocolConstants.ALARM_STATUS_END)) {
                System.out.printf("Received alarm: 0x%04X = %d%n",
                        alarm.id, alarm.value[0]);
            }
        }
    }
}